package scatter.captcha.rest.service.impl;

import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import scatter.captcha.rest.filter.PatternConfigProperties;
import scatter.captcha.rest.service.ICaptchaPreventService;
import scatter.captcha.rest.service.ICaptchaPreventStoreService;
import scatter.captcha.rest.tools.RequestPurposeTools;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * Created by yangwei
 * Created at 2021/1/19 10:02
 */
@Service
public class CaptchaPreventServiceImpl implements ICaptchaPreventService {

    @Autowired
    private ICaptchaPreventStoreService iCaptchaPreventStoreService;
    @Autowired
    private PatternConfigProperties patternConfigProperties;

    @Override
    public void setShouldValidate(String purpose,  HttpServletRequest request) {
        doSetShouldValidate(purpose, true, request);
    }

    @Override
    public void setShouldValidate(String purpose, boolean should, HttpServletRequest request) {

        iCaptchaPreventStoreService.save(purpose,should, request);
    }

    @Override
    public void reset(String purpose, HttpServletRequest request) {
        PatternConfigProperties.CaptchaPreventConfig captchaPreventConfig = matchConfig(purpose);
        Boolean o = (Boolean) iCaptchaPreventStoreService.get(purpose, request);
        if (captchaPreventConfig != null && o != null &&  o == true) {
            if (!captchaPreventConfig.isIgnoreCount()) {
                iCaptchaPreventStoreService.clear(purpose + "_count", request);
            }
            iCaptchaPreventStoreService.clear(purpose, request);
        }

    }

    /**
     * 获取配置
     * @param purpose
     * @return
     */
    private PatternConfigProperties.CaptchaPreventConfig matchConfig(String purpose) {
        PatternConfigProperties.CaptchaPreventConfig captchaPreventConfig = Optional.ofNullable(patternConfigProperties.getPreventConfigs())
                .map(item -> item.stream()
                        .filter(config ->
                                StrUtil.equals(config.getPurpose(), purpose))
                        .findFirst().orElse(null)).orElse(null);
        return captchaPreventConfig;
    }
    /**
     * 验证码需要验证逻辑
     * @param purpose
     * @param count 是否进行计数，如果不计数，仅考虑配置（幂等），否则不幂等
     */
    private void doSetShouldValidate(String purpose, boolean count,  HttpServletRequest request) {
        PatternConfigProperties.CaptchaPreventConfig captchaPreventConfig = matchConfig(purpose);
        // 配置是否存在
        if (captchaPreventConfig != null) {
            // 如果配置存在且配置直接需要验证码
            boolean shouldSave = captchaPreventConfig.getErrorCount() <= 0;
            if (shouldSave) {
                setShouldValidate(purpose,true, request);
                return;
            }
            if(!count){
                return;
            }
            // 否则根据配置计数
            Object o = iCaptchaPreventStoreService.get(purpose + "_count", request);
            if (o == null) {
                o = new Integer(1);
            }else {
                o = (Integer) o + 1;
            }
            iCaptchaPreventStoreService.save(purpose + "_count",o , request);
            // 计数达到阈值，需要验证码验证
            if((Integer) o >= captchaPreventConfig.getErrorCount()){
                setShouldValidate(purpose,true, request);
            }
        }
    }
    @Override
    public boolean isShouldValidate(String purpose,  HttpServletRequest request) {
        Boolean o = (Boolean) iCaptchaPreventStoreService.get(purpose, request);
        if( o != null){
            return o;
        }
        doSetShouldValidate(purpose, false, request);
        o = (Boolean) iCaptchaPreventStoreService.get(purpose, request);
        if( o != null){
            return o;
        }
        return false;
    }
}
